package com.yeskery.nut.script.function.common;

import com.yeskery.nut.script.function.BaseMultiParamFunction;

import java.util.Arrays;

/**
 * 验证函数
 * @author sprout
 * @version 1.0
 * 2022-07-19 23:07
 */
public class ValidFunction extends BaseMultiParamFunction {
    /** 等于 */
    private static final int MATCH_MODEL_EQUALS = 0;
    /** 不等 */
    private static final int MATCH_MODEL_NOT_EQUALS = 1;
    /** 大于 */
    private static final int MATCH_MODEL_GREATER = 2;
    /** 大于等于 */
    private static final int MATCH_MODEL_GREATER_EQUALS = 3;
    /** 小于 */
    private static final int MATCH_MODEL_LESS = 4;
    /** 小于等于 */
    private static final int MATCH_MODEL_LESS_EQUALS = 5;
    /** OR正则表达式 */
    private static final String OR_PATTERN = "\\|\\|";
    /** AND正则表达式 */
    private static final String AND_PATTERN = "&&";
    /** 不等正则表达式 */
    private static final String NOT_EQUALS_PATTERN = "!=";
    /** 等值正则表达式 */
    private static final String EQUALS_PATTERN = "==";
    /** 大于正则表达式 */
    private static final String GREATER_PATTERN = ">";
    /** 大于正则表达式 */
    private static final String GREATER_EQUALS_PATTERN = ">=";
    /** 小于正则表达式 */
    private static final String LESS_PATTERN = "<";
    /** 小于正则表达式 */
    private static final String LESS_EQUALS_PATTERN = "<=";
    /** 空字符串 */
    private static final String EMPTY_STRING = "";
    /** 假字符串 */
    private static final String TRUE_STRING = "1";
    /** 假字符串 */
    private static final String FALSE_STRING = "0";

    @Override
    public String getName() {
        return "valid";
    }

    @Override
    protected String doParams1(String param) {
        return doParams3(new String[]{param, TRUE_STRING, FALSE_STRING}, param);
    }

    @Override
    protected String doParams2(String[] params, String content) {
        return doParams3(new String[]{params[0], params[1], FALSE_STRING}, content);
    }

    @Override
    protected String doParams3(String[] params, String content) {
        String expression = params[0];
        return executeExpression(expression) ? params[1] : params[2];
    }

    /**
     * 验证表达式是否为真
     * @param expression 表达式
     * @return 表达式是否为真
     */
    private boolean executeExpression(String expression) {
        String[] ors = expression.split(OR_PATTERN);
        if (ors.length == 1) {
            String[] ands = ors[0].split(AND_PATTERN);
            if (ands.length == 1) {
                return match(ands[0]);
            } else {
                return Arrays.stream(ands).allMatch(this::match);
            }
        } else {
            for (String or : ors) {
                String[] ands = or.split(AND_PATTERN);
                if (ands.length == 1) {
                    if (match(ands[0])) {
                        return true;
                    }
                } else {
                    if (Arrays.stream(ands).allMatch(this::match)) {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    /**
     * 判断表达式是否匹配
     * @param expression 表达式
     * @return 表达式是否匹配
     */
    private boolean match(String expression) {
        if (expression.contains(NOT_EQUALS_PATTERN)) {
            int index = expression.indexOf(NOT_EQUALS_PATTERN);
            if (index == expression.length() - NOT_EQUALS_PATTERN.length()) {
                return equalsExpression(expression.substring(0, expression.length() - NOT_EQUALS_PATTERN.length()),
                        EMPTY_STRING, MATCH_MODEL_NOT_EQUALS);
            } else {
                String expression1 = expression.substring(0, index);
                String expression2 = expression.substring(index + 2);
                return equalsExpression(expression1, expression2, MATCH_MODEL_NOT_EQUALS);
            }
        } else if (expression.contains(EQUALS_PATTERN)) {
            int index = expression.indexOf(EQUALS_PATTERN);
            if (index == expression.length() - EQUALS_PATTERN.length()) {
                return equalsExpression(expression.substring(0, expression.length() - EQUALS_PATTERN.length()),
                        EMPTY_STRING, MATCH_MODEL_EQUALS);
            } else {
                String expression1 = expression.substring(0, index);
                String expression2 = expression.substring(index + 2);
                return equalsExpression(expression1, expression2, MATCH_MODEL_EQUALS);
            }
        } else if (expression.contains(GREATER_EQUALS_PATTERN)) {
            int index = expression.indexOf(GREATER_EQUALS_PATTERN);
            if (index == expression.length() - GREATER_EQUALS_PATTERN.length()) {
                return equalsExpression(expression.substring(0, expression.length() - GREATER_EQUALS_PATTERN.length()),
                        EMPTY_STRING, MATCH_MODEL_GREATER_EQUALS);
            } else {
                String expression1 = expression.substring(0, index);
                String expression2 = expression.substring(index + 2);
                return equalsExpression(expression1, expression2, MATCH_MODEL_GREATER_EQUALS);
            }
        } else if (expression.contains(GREATER_PATTERN)) {
            int index = expression.indexOf(GREATER_PATTERN);
            if (index == expression.length() - GREATER_PATTERN.length()) {
                return equalsExpression(expression.substring(0, expression.length() - GREATER_PATTERN.length()),
                        EMPTY_STRING, MATCH_MODEL_GREATER);
            } else {
                String expression1 = expression.substring(0, index);
                String expression2 = expression.substring(index + 2);
                return equalsExpression(expression1, expression2, MATCH_MODEL_GREATER);
            }
        } else if (expression.contains(LESS_EQUALS_PATTERN)) {
            int index = expression.indexOf(LESS_EQUALS_PATTERN);
            if (index == expression.length() - LESS_EQUALS_PATTERN.length()) {
                return equalsExpression(expression.substring(0, expression.length() - LESS_EQUALS_PATTERN.length()),
                        EMPTY_STRING, MATCH_MODEL_LESS_EQUALS);
            } else {
                String expression1 = expression.substring(0, index);
                String expression2 = expression.substring(index + 2);
                return equalsExpression(expression1, expression2, MATCH_MODEL_LESS_EQUALS);
            }
        } else if (expression.contains(LESS_PATTERN)) {
            int index = expression.indexOf(LESS_PATTERN);
            if (index == expression.length() - LESS_PATTERN.length()) {
                return equalsExpression(expression.substring(0, expression.length() - LESS_PATTERN.length()),
                        EMPTY_STRING, MATCH_MODEL_LESS);
            } else {
                String expression1 = expression.substring(0, index);
                String expression2 = expression.substring(index + 2);
                return equalsExpression(expression1, expression2, MATCH_MODEL_LESS);
            }
        }
        return isTrue(expression);
    }

    /**
     * 判断表达式为真
     * @param expression 表达式
     * @return 表达式为真
     */
    private boolean isTrue(String expression) {
        expression = expression.trim();
        return !(Boolean.FALSE.toString().equalsIgnoreCase(expression) || FALSE_STRING.equalsIgnoreCase(expression));
    }

    /**
     * 比较两个表达式是否一致
     * @param expression1 表达式1
     * @param expression2 表达式2
     * @param model 比较模式 0等于 1大于 2大于等于 3小于 4小于等于
     * @return 两个表达式是否一致
     */
    private static boolean equalsExpression(String expression1, String expression2, int model) {
        expression1 = expression1.trim();
        expression2 = expression2.trim();
        if (model == MATCH_MODEL_EQUALS) {
            return expression1.compareTo(expression2) == 0;
        } else if (model == MATCH_MODEL_NOT_EQUALS) {
            return expression1.compareTo(expression2) != 0;
        } else if (model == MATCH_MODEL_GREATER) {
            return expression1.compareTo(expression2) > 0;
        } else if (model == MATCH_MODEL_GREATER_EQUALS) {
            return expression1.compareTo(expression2) >= 0;
        } else if (model == MATCH_MODEL_LESS) {
            return expression1.compareTo(expression2) < 0;
        } else if (model == MATCH_MODEL_LESS_EQUALS) {
            return expression1.compareTo(expression2) <= 0;
        }
        return false;
    }
}
